<!-- 模型树数据 -->
<template>
  <div class="model-tree">
    <div class="page-title">
      <span class="page-title-text">物理模型</span>
      <div>
        <el-dropdown size="small" @command="handleCommand">
          <el-button type="primary" size="small">
            新增模型
            <i class="el-icon-arrow-down el-icon--right"></i>
          </el-button>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item command="addModel"> 新增模型 </el-dropdown-item>
              <el-dropdown-item command="batchAddModel">
                批量新增模型
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
    </div>
    <div class="tree-search">
      <el-input
        v-model="filterText"
        size="small"
        placeholder="请输入过滤关键词"
        @input="filterTree"
        style="margin-bottom: 10px"
      ></el-input>
    </div>
    <div class="tree-container">
      <el-tree
        ref="treeRef"
        class="tree-list filter-tree tree-scrollbar"
        node-key="id"
        :props="defaultProps"
        draggable
        lazy
        :load="loadTree"
        :default-expand-all="false"
        render-after-expand
        auto-expand-parent
        :default-expanded-keys="defaultExpandArr"
        :highlight-current="true"
        :filter-node-method="filterMethod"
        :expand-on-click-node="true"
        @node-click="handleNodeClick"
      >
        <template #default="{ node, data }">
          <span class="custom-tree-node">
            <span class="node-left">
              <i class="node-icon">
                <img
                  v-if="data?.type == 4 && data?.modelStatus !== 0"
                  src="../../../../assets/img/model/model.png"
                />
                <img
                  v-else-if="data?.type == 4"
                  src="../../../../assets/img/model/notmodel.png"
                />
                <img v-else src="../../../../assets/img/model/field.png" />
              </i>
              <span class="node-label" :title="node.label">
                {{ node.label }}
              </span>
            </span>

            <span class="node-right">
              <el-dropdown
                v-if="data.type == 3"
                size="small"
                @command="handleCommand"
              >
                <i class="el-icon-plus"></i>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item command="addModel">
                      新建模型
                    </el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
              <el-dropdown
                v-if="[4, 5].includes(data.type)"
                size="small"
                @command="handleParamsCommand"
              >
                <i class="el-icon-more"></i>
                <template #dropdown>
                  <el-dropdown-menu>
                    <el-dropdown-item
                      v-if="modeledArr.includes(data.modelStatus)"
                      :command="{ command: 'modelDetail', data }"
                    >
                      详情
                    </el-dropdown-item>
                    <el-dropdown-item
                      v-if="data.modelStatus === 0"
                      :command="{ command: 'setUpTable', data }"
                    >
                      建表
                    </el-dropdown-item>
                    <el-dropdown-item
                      v-if="data.modelStatus === 0"
                      :command="{ command: 'editDataSource', data }"
                    >
                      编辑表
                    </el-dropdown-item>
                    <el-dropdown-item
                      :command="{ command: 'delDataSource', data }"
                    >
                      删除表
                    </el-dropdown-item>
                    <el-dropdown-item
                      v-if="data.modelStatus > 0"
                      :command="{ command: 'changeStatus', data }"
                    >
                      {{ data.modelStatus === 2 ? "启用" : "禁用" }}
                    </el-dropdown-item>
                  </el-dropdown-menu>
                </template>
              </el-dropdown>
            </span>
          </span>
        </template>
      </el-tree>
    </div>
    <BatchDialog
      :data-bases="dataBases"
      ref="batchDialogRef"
      @reload="reloadTree"
    />
    <OperaModel
      :data-bases="dataBases"
      ref="operaModelRef"
      @reload="reloadTree"
    />
    <ModelDetail :data-bases="dataBases" ref="modelDetailRef" />
  </div>
</template>
<script>
import BatchDialog from "./treeComponents/BatchDialog.vue";
import OperaModel from "./treeComponents/OperaModel.vue";
import ModelDetail from "./treeComponents/ModelDetail.vue";
export default {
  name: "ModelTree",
  components: {
    BatchDialog,
    OperaModel,
    ModelDetail,
  },
  data() {
    return {
      filterText: null,
      // 树数据
      treeData: [],
      defaultProps: {
        label: "name",
        children: "children",
        isLeaf: (data, node) => {
          return !data.childNum || data?.childNum === 0;
        },
      },
      // 默认展开项
      defaultExpandArr: [],
      // 选中域
      curSchema: {},
      // 当前选择节点的详细数据
      curItem: {},
      // 已建表状态 1启用 2禁用 0草稿
      modeledArr: [1, 2],
      // 数据库信息
      dataBases: [],
    };
  },
  created() {
    this.getDataBaseInfo();
  },
  methods: {
    // 获取数据库信息
    getDataBaseInfo() {
      this.$axios
        .get(this.$api.dataConnection.physicalModel.getDataBases, {
          params: { targetType: "all" },
        })
        .then((res) => {
          if (res.data.code === 200) {
            this.dataBases = res.data.data || [];
          } else {
            this.$message.warning(res.data.message);
          }
        });
    },
    async getTreeData(node) {
      if (node) {
        const params = { id: node.data.id, type: node.data.type };
        try {
          const res = await this.$axios.post(
            this.$api.dataConnection.physicalModel.getModelTree,
            params
          );
          const { code, data } = res.data;
          if (code === 200) {
            return data;
          } else {
            return [];
          }
        } catch {
          return [];
        }
      } else {
        try {
          const res = await this.$axios.post(
            this.$api.dataConnection.physicalModel.getModelTree,
            {}
          );
          const { code, data } = res.data;
          if (code === 200) {
            this.treeData = data;
            this.getDefaultShowNodes(2, this.treeData);
          }
        } catch {}
      }
    },
    // 获取模型树信息
    async loadTree(node, resolve) {
      if (node.level === 0) {
        await this.getTreeData();
        return resolve(this.treeData);
      }
      if (node.level === 1) {
        return resolve(this.treeData[0].children);
      }
      if (node.level === 2) {
        const data = this.treeData[0].children.find(
          (item) => item.name === node.data.name
        );
        return resolve(data.children);
      }
      if (node.level === 3) {
        const tables = await this.getTreeData(node);
        return resolve(tables);
      }
      if (node.level > 3) {
        return resolve([]);
      }
    },
    getDefaultShowNodes(num, children) {
      --num;
      if (num >= 0) {
        for (let i = 0; i < children.length; i++) {
          this.defaultExpandArr.push(children[i]?.id);
          if (children[i]?.children) {
            this.getDefaultShowNodes(num, children[i]?.children);
          }
        }
      }
    },
    reloadTree() {
      const rootId = this.treeData[0].id;
      const rootNode = this.$refs.treeRef.getNode(rootId);
      rootNode.loaded = false;
      rootNode.expand();
    },
    // 左侧树顶部操作
    handleCommand(key) {
      const command = this[key];
      if (typeof command === "function") {
        command.call(this);
      }
    },
    // 新增模型
    addModel() {
      this.$refs.operaModelRef.openDialog();
    },
    // 批量新增模型
    batchAddModel() {
      this.$refs.batchDialogRef.openDialog();
    },
    // 处理下拉操作
    handleParamsCommand(info) {
      const command = this[info.command];
      if (typeof command === "function") {
        command.call(this, info.data);
      }
    },
    filterTree(val) {
      this.$refs.treeRef.filter(val);
    },
    // 过滤方法
    filterMethod(value, data) {
      return data.name?.includes(value);
    },
    // 点击节点
    handleNodeClick(data, node) {
      this.curItem = data;
      if (data.type === 3) {
        this.curSchema = data;
        this.$emit("select-schema", data);
        // 选择域时置空模型信息
        this.curItem = {};
        this.$emit("select-model", this.curItem);
      }
      if ([4, 5].includes(data.type)) {
        this.getModelInfo(data).then((res) => {
          if (typeof res === "object") {
            this.curItem = Object.assign(this.curItem, res);
          }
          this.$emit("select-model", this.curItem);
        });
      }
    },
    // 获取模型的表字段 表信息 关联信息
    getModelInfo(data) {
      return new Promise((resolve, reject) => {
        this.$axios
          .get(this.$api.dataConnection.physicalModel.getModelDetail, {
            params: { id: data.id },
          })
          .then((res) => {
            resolve(res.data.data);
          })
          .catch((e) => {
            reject(e);
          });
      });
    },
    // 模型详情
    modelDetail(data) {
      this.getModelInfo(data)
        .then((res) => {
          data = Object.assign(data, res);
          this.$refs.modelDetailRef.openDialog(data);
        })
        .catch((e) => {
          this.$message.error(e.message);
        });
    },
    // 建表
    async setUpTable(data) {
      try {
        const res = await this.getModelInfo(data);
        if (res.localFieldList.length === 0) {
          // 表字段为空时 手动选择该数据 提示需要添加表字段
          this.$refs.treeRef.setCurrentKey(data.id);
          this.curItem = data;
          this.$emit("select-model", this.curItem);
          return this.$message.warning("表字段为空，请先添加表字段");
        }
        this.$axios
          .post(this.$api.dataConnection.physicalModel.createTable, {
            modelId: data.id,
          })
          .then((res) => {
            if (res.data.code === 200) {
              this.$message.success(res.data.message);
              this.reloadTree();
            }
          })
          .catch((err) => {
            this.$message.error(err.message);
          });
      } catch {}
    },
    // 编辑表
    editDataSource(data) {
      this.getModelInfo(data)
        .then((res) => {
          data = Object.assign(data, res);
          this.$refs.operaModelRef.openDialog(data);
        })
        .catch((e) => {
          this.$message.error(e.message);
        });
    },
    // 删除表
    delDataSource(data) {
      this.$confirm("确定删除此表？", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.$axios
            .get(this.$api.dataConnection.physicalModel.deleteModel, {
              params: { id: data.id },
            })
            .then((res) => {
              if (res.data.code === 200) {
                this.$message.success(res.data.message);
                this.$refs.treeRef.remove(data);
                // 如果当前选中了被删除的模型 则需要置空选择项
                if (this.curItem.id === data.id) {
                  this.curItem = {};
                  this.$emit("select-model", this.curItem);
                }
              } else {
                this.$message.warning(res.data.message);
              }
            });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },
    // 启用禁用
    changeStatus(data) {
      this.$confirm(
        `是否确认${data.modelStatus === 2 ? "启用" : "禁用"}该表？`,
        "提示",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        }
      )
        .then(() => {
          this.$axios
            .get(this.$api.dataConnection.physicalModel.changeStatusTable, {
              params: { id: data.id },
            })
            .then((res) => {
              if (res.data.code === 200) {
                this.$message.success(res.data.message);
                data.modelStatus = data.modelStatus === 2 ? 1 : 2;
              }
            });
        })
        .catch(() => {
          this.$message.info("已取消");
        });
    },
  },
};
</script>
<style lang="scss" scoped>
.model-tree {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  height: 100%;
  padding: 20px;
  background-color: #fff;
}
.page-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
  .page-title-text {
    border-left: 5px solid $--color-primary;
    padding-left: 10px;
    margin: 8px 0;
    font-size: 16px;
    line-height: 16px;
  }
}

.tree-container {
  flex: 1;
  padding: 10px 20px;
  overflow-y: auto;
}

.custom-tree-node {
  flex: 1;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  .node-left {
    flex: 1;
    overflow: hidden;
    display: flex;
    align-items: center;
    .node-label {
      flex: 1;
      overflow: hidden;
      text-overflow: ellipsis;
    }
  }
  .node-icon {
    margin-right: 6px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
  }
  .node-right {
    opacity: 0;
    margin: 0 10px;
  }
  &:hover .node-right {
    opacity: 1;
  }
  &:hover span {
    color: $--color-primary;
  }
}
</style>
